package com.example.tripmasternew

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Color
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.*
import android.view.MotionEvent
import android.view.View
import android.view.GestureDetector
import android.view.inputmethod.InputMethodManager
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import kotlin.math.roundToInt
import android.widget.SeekBar

class MainActivity : AppCompatActivity(), LocationListener {

    private val capHistory = mutableListOf<Int>()
    private val capSmoothWindow = 5
    private var lastSmoothedCap = -1
    private var countdownRunning = false
    private var remainingSeconds = 0
    private val timerHandler = Handler(Looper.getMainLooper())
    private val timerRunnable = object : Runnable {
        override fun run() {
            if (remainingSeconds > 0) {
                remainingSeconds--
                timer.text = formatSeconds(remainingSeconds)
                timerHandler.postDelayed(this, 1000)
            } else {
                countdownRunning = false
                if (!isFinishing && !isDestroyed) {
                    runOnUiThread {
                        Toast.makeText(this@MainActivity, "⏰ Timer terminato", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }
    }

    private lateinit var progLeft: View
    private lateinit var progRight: View
    private lateinit var progDisplay: TextView
    private lateinit var cap: TextView
    private lateinit var speed: TextView
    private lateinit var odometerPartial: TextView
    private lateinit var noteDisplay: TextView
    private lateinit var timer: TextView
    private lateinit var clock: TextView
    private lateinit var gpsStatus: TextView
    private lateinit var locationManager: LocationManager
    private var wakeLock: PowerManager.WakeLock? = null
    private val clockHandler = Handler(Looper.getMainLooper())
    private val updateHandler = Handler(Looper.getMainLooper())
    private val autosaveHandler = Handler(Looper.getMainLooper())
    private val autosaveRunnable = object : Runnable {
        override fun run() {
            salvaStato()
            autosaveHandler.postDelayed(this, 2000)
        }
    }

    private val updateClockRunnable = object : Runnable {
        override fun run() {
            if (!isFinishing && !isDestroyed) {
                val currentTime = System.currentTimeMillis()
                val timeFormatted = android.text.format.DateFormat.format("HH:mm:ss", currentTime)
                clock.text = timeFormatted
                clockHandler.postDelayed(this, 1000)
            }
        }
    }

    private var progressiveMeters = 0.0
    private var partialMeters = 0.0
    private var notaCount = 1
    private var lastNotaTapTime = 0L
    private var lastTimerTapTime = 0L

    private var lastProgTapTime = 0L
    private var progTapCount = 0
    private var lastLocation: Location? = null
    private var sensitivityLevel = 1
    private lateinit var gestureDetector: GestureDetector
    private var lastTapTime = 0L
    private var tapCount = 0

    private var isUpdating = false
    private var updateRunnable: Runnable? = null

    @SuppressLint("ClickableViewAccessibility", "SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        autosaveHandler.postDelayed(autosaveRunnable, 2000)

        val prefs = getSharedPreferences("TripMasterPrefs", MODE_PRIVATE)
        progressiveMeters = prefs.getFloat("progressiveMeters", 0f).toDouble()
        partialMeters = prefs.getFloat("partialMeters", 0f).toDouble()
        notaCount = prefs.getInt("notaCount", 1)

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION
                ),
                1001
            )
            return
        }

        val powerManager = getSystemService(POWER_SERVICE) as PowerManager
        wakeLock = powerManager.newWakeLock(
            PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
            "TripMaster::WakeLock"
        )
        wakeLock?.acquire()
        gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
            override fun onDoubleTap(e: MotionEvent): Boolean {
                showResetDialog()
                return true
            }

            override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
                return true
            }
        })

        progLeft = findViewById(R.id.progLeft)
        progRight = findViewById(R.id.progRight)
        progDisplay = findViewById(R.id.progDisplay)
        cap = findViewById(R.id.cap)
        speed = findViewById(R.id.speed)
        odometerPartial = findViewById(R.id.odometerPartial)
        noteDisplay = findViewById(R.id.noteDisplay)
        clock = findViewById(R.id.clock)
        gpsStatus = findViewById(R.id.gpsStatus)
        timer = findViewById(R.id.timerDisplay)

        updateDisplay()
        updateNotaDisplay()
        clockHandler.post(updateClockRunnable)

        odometerPartial.setOnClickListener {
            partialMeters = 0.0
            notaCount++
            updateNotaDisplay()
            updateDisplay()
        }

        val progTouchListener = View.OnTouchListener { view, event ->
            gestureDetector.onTouchEvent(event)

            val isLeft = view.id == R.id.progLeft
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    lastTapTime = System.currentTimeMillis()
                    updateHandler.postDelayed({
                        val now = System.currentTimeMillis()
                        if (now - lastTapTime >= 1000) {
                            startContinuousUpdate(isLeft)
                        }
                    }, 1000)
                }

                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    val now = System.currentTimeMillis()
                    val duration = now - lastTapTime

                    updateHandler.removeCallbacksAndMessages(null)

                    if (duration < 2000) {
                        progressiveMeters += if (isLeft) -10.0 else 10.0
                        if (progressiveMeters < 0) progressiveMeters = 0.0
                        updateDisplay()
                    } else {
                        stopContinuousUpdate()
                    }
                }
            }
            true
        }

        progLeft.setOnTouchListener(progTouchListener)
        progRight.setOnTouchListener(progTouchListener)

        noteDisplay.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                val now = System.currentTimeMillis()
                if (now - lastNotaTapTime < 500) {
                    return@setOnTouchListener true
                }
                lastNotaTapTime = now

                val viewWidth = v.width
                val tapX = event.x

                if (tapX < viewWidth / 2) {
                    notaCount = maxOf(1, notaCount - 1)
                } else {
                    notaCount += 1
                }

                updateNotaDisplay()

                noteDisplay.setBackgroundColor(Color.YELLOW)
                Handler(Looper.getMainLooper()).postDelayed({
                    noteDisplay.setBackgroundColor(Color.TRANSPARENT)
                }, 150)
            }
            true
        }

        // NUOVA GESTIONE TIMER PIÙ REATTIVA
        timer.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_UP) {
                val currentTime = System.currentTimeMillis()
                val timeDiff = currentTime - lastTimerTapTime
                lastTimerTapTime = currentTime

                if (timeDiff <= 300) {
                    showTimerInputDialog()
                } else {
                    if (!countdownRunning) {
                        if (remainingSeconds > 0) {
                            countdownRunning = true
                            timerHandler.post(timerRunnable)
                        } else {
                            Toast.makeText(this@MainActivity, "Imposta prima un tempo", Toast.LENGTH_SHORT).show()
                        }
                    } else {
                        countdownRunning = false
                        timerHandler.removeCallbacks(timerRunnable)
                    }
                }
            }
            true
        }

        locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 0f, this)
        } catch (e: SecurityException) {
            Toast.makeText(this, "Permesso GPS mancante", Toast.LENGTH_SHORT).show()
        }
    }

    private fun updateNotaDisplay() {
        noteDisplay.text = "Nota: $notaCount"
    }

    private fun salvaStato() {
        val prefs = getSharedPreferences("TripMasterPrefs", MODE_PRIVATE)
        val editor = prefs.edit()
        editor.putFloat("progressiveMeters", progressiveMeters.toFloat())
        editor.putFloat("partialMeters", partialMeters.toFloat())
        editor.putInt("notaCount", notaCount)
        editor.apply()
    }

    private fun showNotaInputDialog() {
        val input = EditText(this).apply {
            inputType = android.text.InputType.TYPE_CLASS_NUMBER
            hint = "Es: 12"
        }

        AlertDialog.Builder(this)
            .setTitle("Modifica numero nota")
            .setView(input)
            .setPositiveButton("OK") { _, _ ->
                val numero = input.text.toString().toIntOrNull()
                if (numero != null) {
                    notaCount = numero
                    updateNotaDisplay()
                }
            }
            .setNegativeButton("Annulla", null)
            .show()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1001) {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                recreate()
            } else {
                Toast.makeText(this, "Permessi GPS negati", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        autosaveHandler.removeCallbacks(autosaveRunnable)
        salvaStato()
        wakeLock?.release()
        timerHandler.removeCallbacksAndMessages(null)
        updateHandler.removeCallbacksAndMessages(null)
        clockHandler.removeCallbacksAndMessages(null)
    }

    private fun handleProgTouch(event: MotionEvent, isLeft: Boolean) {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                val now = System.currentTimeMillis()
                if (now - lastTapTime < 400) {
                    tapCount++
                    if (tapCount == 2) {
                        tapCount = 0
                        showResetDialog()
                        return
                    }
                } else {
                    tapCount = 1
                }
                lastTapTime = now
                startContinuousUpdate(isLeft)
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> stopContinuousUpdate()
        }
    }

    private fun startContinuousUpdate(isLeft: Boolean) {
        isUpdating = true
        val step = if (isLeft) -10.02 else 10.0
        val delay = 5L

        updateRunnable = object : Runnable {
            override fun run() {
                progressiveMeters += step
                if (progressiveMeters < 0) progressiveMeters = 0.0
                updateDisplay()
                if (isUpdating) {
                    updateHandler.postDelayed(this, delay)
                }
            }
        }
        updateHandler.post(updateRunnable!!)
    }

    private fun stopContinuousUpdate() {
        isUpdating = false
        updateRunnable?.let { updateHandler.removeCallbacks(it) }
    }

    private fun updateDisplay() {
        if (!isFinishing && !isDestroyed) {
            progDisplay.text = String.format("%06.2f", progressiveMeters / 1000.0)
            odometerPartial.text = String.format("%06.2f", partialMeters / 1000.0)
        }
    }

    private fun showResetDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog_reset, null)
        val sensitivitySeek = dialogView.findViewById<SeekBar>(R.id.sensitivitySeek)
        val sensitivityValue = dialogView.findViewById<TextView>(R.id.sensitivityValue)

        sensitivitySeek.max = 10
        sensitivitySeek.progress = sensitivityLevel
        sensitivityValue.text = String.format("%.1f km/h", sensitivityLevel / 2.0)

        sensitivitySeek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                sensitivityLevel = progress
                sensitivityValue.text = String.format("%.1f km/h", progress / 2.0)
            }
            override fun onStartTrackingTouch(seekBar: SeekBar?) {}
            override fun onStopTrackingTouch(seekBar: SeekBar?) {}
        })

        AlertDialog.Builder(this)
            .setTitle("Opzioni Prog.")
            .setView(dialogView)
            .setPositiveButton("Resetta km") { _, _ ->
                progressiveMeters = 0.0
                partialMeters = 0.0
                notaCount = 1
                updateNotaDisplay()
                updateDisplay()
            }
            .setNegativeButton("Chiudi", null)
            .show()
    }

    override fun onLocationChanged(location: Location) {
        if (isFinishing || isDestroyed) return

        val speedKmh = location.speed * 3.6
        speed.text = String.format("%.1f km/h", speedKmh)

        val accuracy = location.accuracy
        val provider = location.provider

        val (textColor, statusText, bgColor) = when {
            accuracy <= 10 -> Triple(Color.BLACK, "GPS: OTTIMO", Color.WHITE)
            accuracy <= 30 -> Triple(Color.DKGRAY, "GPS: ACCETTABILE", Color.parseColor("#222222"))
            accuracy <= 50 -> Triple(Color.YELLOW, "GPS: DEBOLE", Color.parseColor("#222222"))
            else -> Triple(Color.RED, "GPS: NON AFFIDABILE", Color.parseColor("#222222"))
        }

        gpsStatus.setTextColor(if (provider != LocationManager.GPS_PROVIDER) Color.parseColor("#FFC107") else textColor)
        gpsStatus.text = "$statusText ($provider)"
        gpsStatus.setBackgroundColor(bgColor)

        if (speedKmh > 2 && lastLocation != null) {
            val rawBearing = lastLocation!!.bearingTo(location)
            val normalizedBearing = ((rawBearing + 360) % 360).roundToInt()

            capHistory.add(normalizedBearing)
            if (capHistory.size > capSmoothWindow) {
                capHistory.removeAt(0)
            }

            val averageCap = capHistory.average().roundToInt()

            if (lastSmoothedCap == -1 || kotlin.math.abs(averageCap - lastSmoothedCap) >= 3) {
                cap.text = averageCap.toString()
                lastSmoothedCap = averageCap
            }
        } else {
            cap.text = "--"
            capHistory.clear()
            lastSmoothedCap = -1
        }

        if (sensitivityLevel == 0 || speedKmh >= sensitivityLevel / 2.0) {
            lastLocation?.let {
                val distance = location.distanceTo(it)
                progressiveMeters += distance
                partialMeters += distance
                updateDisplay()
            }
        }
        lastLocation = location
    }

    private fun showTimerInputDialog() {
        val input = EditText(this).apply {
            inputType = android.text.InputType.TYPE_CLASS_NUMBER
            hint = "Formato: 00:00:00"
            isSingleLine = true
            setRawInputType(Configuration.KEYBOARD_12KEY)

            post {
                requestFocus()
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
            }
        }

        val dialog = AlertDialog.Builder(this)
            .setTitle("Imposta timer")
            .setView(input)
            .setPositiveButton(android.R.string.ok) { _, _ ->
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(input.windowToken, 0)

                val raw = input.text.toString().padStart(6, '0')
                val ore = raw.substring(0, 2).toIntOrNull() ?: 0
                val min = raw.substring(2, 4).toIntOrNull() ?: 0
                val sec = raw.substring(4, 6).toIntOrNull() ?: 0
                remainingSeconds = ore * 3600 + min * 60 + sec
                timer.text = formatSeconds(remainingSeconds)
            }
            .setNegativeButton(android.R.string.cancel) { dialog, _ ->
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(input.windowToken, 0)
                dialog.dismiss()
            }
            .create()

        dialog.setOnDismissListener {
            val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
            imm.hideSoftInputFromWindow(input.windowToken, 0)
        }

        dialog.show()
    }

    private fun formatSeconds(seconds: Int): String {
        val h = seconds / 3600
        val m = (seconds % 3600) / 60
        val s = seconds % 60

        return when {
            h > 0 -> String.format("%d:%02d:%02d", h, m, s)
            else -> String.format("%02d:%02d", m, s)
        }
    }
}